#ifndef _BSC_HTTP_FILE_INTERFACE_H_
#define _BSC_HTTP_FILE_INTERFACE_H_

#include "ofc/ofc_types.h"
#include "ffc/ffc_stream.h"
#include "mfc/mfc_serial_vir_bus.h"

#ifdef __cplusplus
extern "C" {
#endif

struct THttpClientASyncParamTag
{

    /// 公共部分
    UInt16 reconnect_cnt;                 ///< 单次连接重连次数，超过自动取消任务    
    UInt16 recv_timeout;                  ///< 接收超时时间  单位1ms
/// GET
    UInt32 total_reconnect_cnt;           ///< 总重连次数，超过自动取消任务（下载使用)
/// POST
    UInt16 delay_ms;                      ///< 每上传一的延时 单位1ms
/// GET
    UInt8  delay_reconnect_cnt;          ///< 单次连接重试失败后，尝试每半个小时去连接的次数  
/// 用户认证
    Bool  basic_authorization;            ///< 使用用户名密码认证
    char  user[16];                      ///< 用户名  以0结尾
    char  password[20];                  ///< 密码    以0结尾
};
typedef struct THttpClientASyncParamTag THttpClientASyncParam;

/**
 * http任务状态
 */
enum THttpClientTaskStatusTag
{
    kHttpClientTaskNoExist,       ///< 没有这个任务
    kHttpClientTaskNotStart,      ///< 未开始
    //kHttpClientTaskPausing,       ///< 正在暂停
    kHttpClientTaskPaused,        ///< 已暂停
    kHttpClientTaskRunning,       ///< 正在执行
    kHttpClientTaskIdle,          ///< 空闲，已执行完成
};
typedef enum THttpClientTaskStatusTag THttpClientTaskStatus;

/**
 * http通知项
 */
typedef struct TBsHttpClientTaskNotifyItemTag TBsHttpClientTaskNotifyItem;
struct TBsHttpClientTaskNotifyItemTag
{
    Int32  code;            ///< >0: http状态码   <0:错误码
    UInt32 total_size;      ///< 当前下载的总大小
    UInt32 file_size;       ///< 文件总大小
    UInt16 task_id;         ///< 任务id 
    UInt8  task_status;     ///< 任务状态

    UInt32 offset;          ///< get 方法的当前偏移               
    UInt32 current_size;    ///< get 方法当前下载大小

    char  *resp;            ///< post方法返回的数据
    UInt16 resp_len;        ///< post方法返回的数据长度
};

typedef void (*TBsHttpClientTaskDoNotify)(void *user_param, TBsHttpClientTaskNotifyItem *notify_item);

/**
 * http通知事件
 */
typedef struct TBsHttpClientTaskOnNotifyTag TBsHttpClientTaskOnNotify;
struct TBsHttpClientTaskOnNotifyTag
{
    void *user_param;
    TBsHttpClientTaskDoNotify do_notify;
};

typedef struct THttpClientSyncParamTag THttpClientSyncParam;
struct THttpClientSyncParamTag
{
    const char    *uri;
    const char    *add_header;    
    char          *resp_buffer;
    UInt32        resp_size;

    UInt16        recv_timeout;
};

/**
 * HTTP Client Get方法获取文件  (异步方式)
 * @param ff_stream: 数据流
 * @param uri:  链接 
 * @param offset: 文件偏移地址
 * @param size: 读取大小 
 * @param param: 连接参数 
 * @note 当size过大，文件将进行分包存储，每次完成存储后都会通过事件通知，获取任务id后，需要调用http_task启动
 * @note 下载的断点续传有两种方式，传递offset或者按照数据流的位置进行偏移，两种同时支持
 * @return >=0:任务id <0:错误码
 */
Int32 BsHttpClientASyncGet(const char *uri, Int32 offset, Int32 size, const THttpClientASyncParam *param); 

/**
 * HTTP Client Post方法上传文件  (异步方式)
 * @param ff_stream: 数据流
 * @param uri:  链接 
 * @param form_data: 表单数据
 * @param param: 连接参数 
 * @note 文件全部上传完成后进行事件通知，获取任务id后，需要调用http_task启动
 * @return >=0:任务id <0:错误码
 */
Int32 BsHttpClientASyncPost(const char *uri, const char *form_data, const THttpClientASyncParam *param);

/**
 * 启动http任务
 * @param task_id: 任务id
 * @param ff_stream: 文件流
 * @param vir_bus: 虚拟总线
 * @param on_notify: 通知事件  
 * @note 下载的断点续传有两种方式，BsHttpClientGetFile传递offset参数或者按照数据流的位置进行偏移，两种同时支持
 * @note 新任务数据流的偏移应该从0开始
 * @note 受并发数限制，其他任务正在下载，不一定启动成功
 * @return >=0:成功 <0:错误码
 */
Int32 HttpClientTaskResume(UInt16 task_id, TFfStream *ff_stream, TMfSerialVirBus *vir_bus, const TBsHttpClientTaskOnNotify *on_notify);

/**
 * 暂停http任务
 * @param task_id: 任务id
 * @return >=0:成功 <0:错误码
 */
Int32 HttpClientTaskPause(UInt16 task_id);

/**
 * 删除http任务
 * @param task_id: 任务id
 * @return >=0:成功 <0:错误码
 * @note 需要检查返回值，当其他任务正在执行，函数执行时间最长4S
 */
Int32 HttpClientTaskDelete(UInt16 task_id);

/**
 * http任务状态查询
 * @param task_id: 任务id
 * @param progress: 当前进度 %, -1不支持
 * @param speed: 速度 byte/s, -1不支持
 * @param use_time: 已用时间 s, -1不支持
 * @param left_time: 剩余时间 s, -1不支持
 * @return 参考 @ref THttpClientTaskStatus
 */
Int32 HttpClientTaskGetStatus(UInt16 task_id, Int8 *progress, Int32 *speed, Int32 *use_time, Int32 *left_time);

typedef struct THttpClientTaskTaskProgressTag THttpClientTaskTaskProgress;
struct THttpClientTaskTaskProgressTag
{
    Int8 progress;   ///< 本次下载进度 %
    Int32 speed;     ///< 速度 byte/s
    Int32 use_time;  ///< 已用时间 s
    Int32 left_time; ///< 剩余时间 s
    Int32 total_progress; ///< 总进度 %
};

/**
 * http任务状态查询
 * @param task_id: 任务id
 * @param process: 进度
 * @return 参考 @ref THttpClientTaskStatus
 */
Int32 HttpClientTaskGetStatusEx(UInt16 task_id, THttpClientTaskTaskProgress *progress);

typedef void (*HttpClientTaskDoGetTaskId)(UInt16 task_id, void *user_param);

/**
 * 枚举http任务 task id
 * @param do_get_task_id: 回调函数
 * @return
 */
void HttpClientTaskEnumTaskId(HttpClientTaskDoGetTaskId do_get_task_id, void *user_param);

/**
 * HTTP Client Get方法 (同步方式)
 * @param vir_bus: 虚拟总线
 * @param param:  参数 
 * @param resp_length:  返回数据长度
 * @return >0: http状态码   <0:错误码
 */
Int32 BsHttpClientSyncGet(TMfSerialVirBus *vir_bus, const THttpClientSyncParam *param, UInt32 *resp_length);

/**
 * HTTP Client post方法 (同步方式)
 * @param vir_bus: 虚拟总线 
 * @param param:  参数 
 * @param resp_length: 返回数据长度
 * @param post_data: 表单数据 
 * @param post_data_length: 表单数据长度 
 * @return >0: http状态码   <0:错误码
 */
Int32 BsHttpClientSyncPost(TMfSerialVirBus *vir_bus, const THttpClientSyncParam *param, UInt32 *resp_length, 
    const char *post_data, UInt16 post_data_length);

///**
// * HTTP Client Put方法 (同步方式)
// * @param vir_bus: 虚拟总线
// * @param param:  参数 
// * @param resp_length:  返回数据长度
// * @return >0: http状态码   <0:错误码
// */
//Int32 BsHttpClientSyncPut(TMfSerialVirBus *vir_bus, const THttpClientSyncParam *param, UInt16 *resp_length);
//
///**
// * HTTP Client Delete方法 (同步方式)
// * @param vir_bus: 虚拟总线 
// * @param param:  参数 
// * @param resp_length:  返回数据长度
// * @return >0: http状态码   <0:错误码
// */
//Int32 BsHttpClientSyncDelete(TMfSerialVirBus *vir_bus, const THttpClientSyncParam *param, UInt16 *resp_length);

#ifdef __cplusplus
} // extern "C" {
#endif
#endif
